//
//  ZealcommNetWorkTool.m
//  irtc_sipcall
//
//  Created by zealcomm user on 2020/4/21.
//  Copyright © 2020 zealcomm user. All rights reserved.
//

#import "ZealcommNetWorkTool.h"

//分隔符
#define YFBoundary @"WebKitFormBoundaryXGYtOdQDcAok6XkK"
//换行
#define YFEnter [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
//NSString转NSData
#define YFEncode(string) [string dataUsingEncoding:NSUTF8StringEncoding]

static  NSString *apiErrorDomain = @"zealcomm.ivcs.api";

@interface ZealcommNetWorkTool()<NSURLSessionDelegate,NSURLSessionTaskDelegate>

@end
@implementation ZealcommNetWorkTool

#pragma mark 创建单例
relizeSingleInstance(NetWorkTool)

#pragma mark 实现头文件中的方法
-(void)GET:(NSString *)url parameters:(id)parameters HeaderKeyValues:(NSDictionary *)header success:(void (^)(id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure{
    NSDictionary *temp = parameters;
    if(temp){
        NSString *path = @"";
        for (NSString *key in temp.allKeys) {
            path = [NSString stringWithFormat:@"%@%@=%@&" , path , key , [temp valueForKey:key]];
        }
        if (path.length > 0) {
            url = [NSString stringWithFormat:@"%@?%@" , url , [path substringToIndex:path.length - 1]];
        }
    }
    NSURL *requestUrl = [NSURL URLWithString:url];
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:requestUrl];
    //    NSURLRequest *request = [NSURLRequest requestWithURL:requestUrl];
    //    MyLog(@"request,header=%@",request.allHTTPHeaderFields);
    [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    if (header) {
        for (NSString *key in header.allKeys) {
            [request addValue:[header valueForKey:key] forHTTPHeaderField:key];
        }
    }
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                          delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        MyLog(@"request url=%@,\r\tmethod=GET,\r\theader=%@,\r\tbody=%@,\r\tresponseData=%@,\r\terror=%@" , url , request.allHTTPHeaderFields , [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] , [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] , error);
        if (error == nil) {
            //NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
            success(data);
        }else{
            failure(error);
        }
    }];
    [task resume];
}

-(void)POST:(NSString *)url parameters:(id)parameters HeaderKeyValues:(NSDictionary *)header success:(void (^)(id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure{
    NSURL *requestUrl = [NSURL URLWithString:url];
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:requestUrl];
    request.HTTPMethod = @"POST";
    if (parameters) {
        NSData *parameterData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:0];
        //NSJSONWritingPrettyPrinted = (1UL << 0) //是将生成的json数据格式化输出，这样可读性高，不设置则输出的json字符串就是一整行。
        request.HTTPBody= parameterData;
    }
    [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    if (header) {
        for (NSString *key in header.allKeys) {
            [request addValue:[header valueForKey:key] forHTTPHeaderField:key];
        }
    }
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                          delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        MyLog(@"request url=%@,\r\tmethod=POST,\r\theader=%@,\r\tbody=%@,\r\tresponseData=%@,\r\terror=%@" , url , request.allHTTPHeaderFields , [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] , [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] , error);
        if (error == nil) {
            long statusCode = (long)[(NSHTTPURLResponse *)response statusCode];
            if (statusCode == 200) {
                success(data);
            }else{
                NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
                NSError *error =[NSError errorWithDomain:apiErrorDomain code:statusCode userInfo:result];
                failure(error);
            }
        }else{
            failure(error);
        }
    }];
    [task resume];
}

-(void)DELETE:(NSString *)url parameters:(id)parameters HeaderKeyValues:(NSDictionary *)header success:(void (^)(id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure{
    NSURL *requestUrl = [NSURL URLWithString:url];
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:requestUrl];
    request.HTTPMethod = @"DELETE";
    [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    if (parameters) {
        NSData *parameterData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:0];
        //NSJSONWritingPrettyPrinted = (1UL << 0) //是将生成的json数据格式化输出，这样可读性高，不设置则输出的json字符串就是一整行。
        request.HTTPBody= parameterData;
    }
    if (header) {
        for (NSString *key in header.allKeys) {
            [request addValue:[header valueForKey:key] forHTTPHeaderField:key];
        }
    }
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                          delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        MyLog(@"request url=%@,\r\tmethod=DELETE,\r\theader=%@,\r\tbody=%@,\r\tresponseData=%@,\r\terror=%@" , url , request.allHTTPHeaderFields , [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] , [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] , error);
        if (error == nil) {
            long statusCode = (long)[(NSHTTPURLResponse *)response statusCode];
            if (statusCode == 200) {
                success(data);
            }else{
                NSError *error =[NSError errorWithDomain:apiErrorDomain code:statusCode userInfo:@{
                    @"description":response.description
                }];
                failure(error);
            }
        }else{
            failure(error);
        }
    }];
    [task resume];
}

-(void)Upload:(NSString *)url fileData:(NSData *)fileData fileName:(NSString *)fileName mimeType:(NSString *)mimeType parameters:(id)parameters HeaderKeyValues:(NSDictionary *)header success:(void (^)(id _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure{
    NSURL *requestUrl = [NSURL URLWithString:url];
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:requestUrl];
    request.HTTPMethod = @"POST";
    if (parameters) {
        NSData *parameterData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:0];
        //NSJSONWritingPrettyPrinted = (1UL << 0) //是将生成的json数据格式化输出，这样可读性高，不设置则输出的json字符串就是一整行。
        request.HTTPBody= parameterData;
    }
    NSString *head = [NSString stringWithFormat:@"multipart/form-data;boundary=%--@", YFBoundary];
    [request setValue:head forHTTPHeaderField:@"Content-Type"];
    
    if (header) {
        for (NSString *key in header.allKeys) {
            [request addValue:[header valueForKey:key] forHTTPHeaderField:key];
        }
    }
    NSData * uploadData = [self getDataWithData:fileData fileName:fileName mimeType:mimeType];
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                          delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:uploadData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        MyLog(@"request url=%@,\r\tmethod=UPLOAD,\r\theader=%@,\r\tbody=%@,\r\tresponseData=%@,\r\terror=%@" , url , request.allHTTPHeaderFields , [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] , [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] , error);
        if (error == nil) {
            long statusCode = (long)[(NSHTTPURLResponse *)response statusCode];
            if (statusCode == 200) {
                success([self returnDictionaryWithDataPath:data]);
            }else{
                NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
                NSError *error =[NSError errorWithDomain:apiErrorDomain code:statusCode userInfo:result];
                failure(error);
            }
        }else{
            failure(error);
        }
    }];
    [uploadTask resume];
}

-(void)Upload:(NSString *)url image:(UIImage *)image fileName:(nonnull NSString *)fileName mimeType:(NSString *)mimeType parameters:(id _Nullable)parameters HeaderKeyValues:(NSDictionary * _Nullable)header success:(nonnull void (^)(id _Nonnull))success failure:(nonnull void (^)(NSError * _Nonnull))failure{
    NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
    [self Upload:url fileData:imageData fileName:fileName mimeType:mimeType parameters:parameters HeaderKeyValues:header success:^(id  _Nonnull responseObject) {
        success(responseObject);
    } failure:^(NSError * _Nonnull error) {
        failure(error);
    }];
}

#pragma mark 实现 NSURLSessionTaskDelegate
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
    MyLog(@"uploadTask progress..%lld..%lld..%lld",bytesSent,totalBytesSent,totalBytesExpectedToSend);
}

#pragma mark 实现 NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
    MyLog(@"didReceiveChallenge,,%@",challenge);
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        //        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        NSString *host = challenge.protectionSpace.host;
        MyLog(@"didReceiveChallenge host=%@", host);
        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];       completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
    }else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]){
        //客户端证书认证
        //TODO: 设置客户端证书认证
        // load cert
        MyLog(@"client");
        NSString *path = [[NSBundle mainBundle]pathForResource:@"client"ofType:@"p12"];
        NSData *p12data = [NSData dataWithContentsOfFile:path];
        CFDataRef inP12data = (__bridge CFDataRef)p12data;
        SecIdentityRef myIdentity;
        OSStatus status = [self extractIdentity:inP12data toIdentity:&myIdentity];
        if (status != 0) {
            return;
        }
        SecCertificateRef myCertificate;
        SecIdentityCopyCertificate(myIdentity, &myCertificate);
        const void *certs[] = { myCertificate };
        CFArrayRef certsArray =CFArrayCreate(NULL, certs,1,NULL);
        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];
        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
    }
}

#pragma mark Others

- (OSStatus)extractIdentity:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
    OSStatus securityError = errSecSuccess;
    CFStringRef password = CFSTR("123456");
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import(inP12Data, options, &items);
    if (securityError == 0)
    {
        CFDictionaryRef ident = CFArrayGetValueAtIndex(items,0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
        *identity = (SecIdentityRef)tempIdentity;
    }
    else
    {
        MyLog(@"clinet.p12 error!");
    }
    
    if (options) {
        CFRelease(options);
    }
    return securityError;
}

-(NSData *)getDataWithData:(NSData *)fileData fileName:(NSString *)fileName mimeType:(NSString *)mimeType
{
    NSMutableData *data = [NSMutableData data];
    //1、开始标记
    //--
    [data appendData:YFEncode(@"--")];
    //boundary
    [data appendData:YFEncode(YFBoundary)];
    //换行符
    [data appendData:YFEnter];
    //key =file
    //文件参数名 Content-Disposition: form-data; name="file"; filename="xxx.jpg"
    NSString *file = [NSString stringWithFormat:@"Content-Disposition:form-data; name=\"file\";filename=\"%@\"",fileName];
    [data appendData:YFEncode(file)];
    //换行符
    [data appendData:YFEnter];
    //Content-Type 上传文件的类型 MIME  @"Content-Type:image/png"
    NSString *fileType = [NSString stringWithFormat:@"Content-Type:%@",mimeType];
    [data appendData:YFEncode(fileType)];
    //换行符
    [data appendData:YFEnter];
    //换行符
    [data appendData:YFEnter];
    //2、上传的文件数据
    [data appendData:fileData];
    //换行符
    [data appendData:YFEnter];
    //3、结束标记
    //--
    [data appendData:YFEncode(@"--")];
    //boundary
    [data appendData:YFEncode(YFBoundary)];
    //--
    [data appendData:YFEncode(@"--")];
    //换行符
    [data appendData:YFEnter];
    return data;
}

-(NSDictionary*)returnDictionaryWithDataPath:(NSData*)data
{
    NSString *receiveStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSData * datas = [receiveStr dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:datas options:NSJSONReadingMutableLeaves error:nil];
    return jsonDict;
}


@end
